package com.ruoyi.web.controller.biz;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.enums.HttpStatusEnum;
import com.ruoyi.common.constant.JingquStatusConstants;
import com.ruoyi.common.constant.OrderConstants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.QRcode;
import com.ruoyi.common.utils.RandomUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.BsJingqu;
import com.ruoyi.system.domain.BsOrderDetails;
import com.ruoyi.system.domain.BsOrderInfo;
import com.ruoyi.system.domain.dto.BsOrderListDto;
import com.ruoyi.system.domain.ro.OrderCount;
import com.ruoyi.system.domain.vo.*;
import com.ruoyi.system.service.BsJingquService;
import com.ruoyi.system.service.BsOrderDetailsService;
import com.ruoyi.system.service.BsOrderInfoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.aspectj.weaver.loadtime.Aj;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

/**
 * @ClassName BsOrderController
 * @Description 描述
 * @Author HanWL
 * @Date 2023/10/18 21:02
 * @Version 1.0
 **/
@RestController
@Api(tags = "购买门票-订单接口")
@RequestMapping("/bs/order")
public class BsOrderController extends BaseController {

    @Resource
    private BsOrderInfoService bsOrderInfoService;
    @Resource
    private BsOrderDetailsService bsOrderDetailsService;
    @Resource
    private BsJingquService bsJingquService;

    @ApiOperation("查询景区选中日期的门票种类及数量")
    @GetMapping("getDayMenpiaoNum")
    public AjaxResult<List<OrderMenpiaoVo>> getDayMenpiaoNum(String date, Long jingquId){
        List<OrderMenpiaoVo> dayMenpiaoNum = bsOrderInfoService.getDayMenpiaoNum(date, jingquId);
        return AjaxResult.success(dayMenpiaoNum);
    }

    @ApiOperation("获取未来7天的门票总量及剩余情况")
    @GetMapping("getFutureMenpiaoNum/{jingquId}")
    public AjaxResult<List<Future7DaysMenpiaoInfoVo>> getFutureMenpiaoNum(@PathVariable Long jingquId){
        List<Future7DaysMenpiaoInfoVo> futureMenpiaoNum = bsOrderInfoService.getFutureMenpiaoNum(jingquId);
        return AjaxResult.success(futureMenpiaoNum);
    }

    @ApiOperation("预约(生成订单)")
    @PostMapping("genOrder")
    @RepeatSubmit
    public AjaxResult<?> genOrder(@RequestBody OrderGenVo orderGenVo){
        // 查询景区状态，是否可预约
        BsJingqu jingqu = bsJingquService.getById(orderGenVo.getJingquId());
        if (jingqu.getJingquStatus().equals(JingquStatusConstants.CLOSE)){
            return AjaxResult.error(HttpStatusEnum.JINGQU_CLOSE_STATUS);
        }
        // 判断当前余票满不满足订单需要的票
        if ( bsOrderInfoService.checkEnoughMenpiaoNum(orderGenVo)){
            return AjaxResult.error(HttpStatusEnum.FAIL_ORDER_NO_MENPIAO_NUM);
        }
        // 检查是否已经预约过，防止重复预约
        if ( bsOrderInfoService.checkAlreadyOrder(orderGenVo)){
            return AjaxResult.error(HttpStatusEnum.FAIL_ORDER_ALREADY_EXIST);
        }
        // 生成订单
        Long orderId = bsOrderInfoService.genOrder(orderGenVo);
        return StringUtils.isNotNull(orderId) ? AjaxResult.success(orderId) : AjaxResult.error();
    }

    @ApiOperation("根据订单ID查询订单详情(支付界面使用)")
    @GetMapping("getOrderDetailsByOrderId/{orderId}")
    public AjaxResult<List<OrderDetailsVo>> getOrderDetailsByOrderId(@PathVariable Long orderId){
        List<OrderDetailsVo> resultList = bsOrderInfoService.getOrderDetailsByOrderId(orderId);
        return AjaxResult.success(resultList);
    }

    @ApiOperation("根据订单ID查询订单详情(我的界面中使用)")
    @GetMapping("getOrderAllDetailsByOrderId/{orderId}")
    public AjaxResult<?> getOrderAllDetailsByOrderId(@PathVariable Long orderId){
        MyOrderDetailsVo vo = bsOrderInfoService.getOrderAllDetailsByOrderId(orderId);
        return AjaxResult.success(vo);
    }

    @ApiOperation("订单列表(我的界面中使用处理中，未出行，待评价)")
    @GetMapping("orderPage")
    public AjaxResult<?> orderPage(Integer status){
        LambdaQueryWrapper<BsOrderInfo> lqw = new LambdaQueryWrapper<>();
        if (status.equals(4)){
            lqw.eq(BsOrderInfo::getOrderPayStatus,0);
            lqw.eq(BsOrderInfo::getOrderUseStatus,status);
        } else if (status.equals(0)){
            lqw.eq(BsOrderInfo::getOrderPayStatus,1);
            lqw.eq(BsOrderInfo::getOrderUseStatus,status);
        } else if (status.equals(1)){
            lqw.eq(BsOrderInfo::getOrderJudgeStatus,0);
            lqw.eq(BsOrderInfo::getOrderUseStatus,status);
        }
        lqw.eq(BsOrderInfo::getUserId, SecurityUtils.getUserId());
        startPage();
        List<BsOrderInfo> list = bsOrderInfoService.list(lqw);
        List<BsOrderListDto> orderDetailsList = bsOrderInfoService.getOrderDetailsList(list);
        return AjaxResult.success(orderDetailsList);
    }

    @ApiOperation("我的界面中，展示待处理，未出行，待评价的数量")
    @GetMapping("/order/count")
    public AjaxResult<?> orderCount(){
        Long userId = SecurityUtils.getUserId();
        OrderCount orderCount = bsOrderInfoService.orderCount(userId);
        return AjaxResult.success(orderCount);
    }

    @ApiOperation("修改订单详情信息(用于订单详情页加减票数)")
    @PutMapping("updateOrderDetails")
    public AjaxResult<?> updateOrderDetails(@RequestBody BsOrderDetails bsOrderDetails){
        boolean result = bsOrderDetailsService.updateNumAndPrice(bsOrderDetails);
        return toAjax(result);
    }

    @ApiOperation("取消订单")
    @PostMapping("/cancelOrder/{orderId}")
    public AjaxResult<?> cancelOrder(@PathVariable Long orderId){
        BsOrderInfo orderInfo = bsOrderInfoService.getById(orderId);
        orderInfo.setOrderUseStatus(OrderConstants.USE_STATUS_CANCEL);
        return toAjax(bsOrderInfoService.updateById(orderInfo));
    }

    @ApiOperation("入园")
    @PostMapping("/enter/{orderId}")
    public AjaxResult<?> enter(@PathVariable Long orderId){
        BsOrderInfo orderInfo = bsOrderInfoService.getById(orderId);
        if (orderInfo.getOrderUseStatus() != OrderConstants.USE_STATUS_WAIT){
            return AjaxResult.error(HttpStatusEnum.STATUS_CHANGE);
        }
        orderInfo.setOrderUseStatus(OrderConstants.USE_STATUS_ALREADY);
        orderInfo.setOrderEnterTime(new Date());
        return toAjax(bsOrderInfoService.updateById(orderInfo));

    }


    @ApiOperation("支付")
    @PostMapping("pay")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult<?> pay(@RequestBody OrderPayVo orderPayVo){
        BsOrderInfo one = bsOrderInfoService.getById(orderPayVo.getOrderId());
        // 处理联系人
        boolean result = bsOrderDetailsService.saveContract(orderPayVo.getContracts());
        // 调用支付接口
        // TODO 调用支付接口
        if (weixinPay()) {
            // 支付成功，生成验证码，二维码，修改订单状态，修改使用状态
            one.setOrderCode(RandomUtils.generate6Char());
            one.setOrderPictureCode(QRcode.generateQRCode(String.valueOf(one.getOrderId())));
            // 修改订单状态为已支付
            one.setOrderPayStatus(OrderConstants.PAY_STATUS_YES);
            // 修改使用状态为待入园
            one.setOrderUseStatus(OrderConstants.USE_STATUS_WAIT);
            return toAjax(bsOrderInfoService.updateById(one));
        }
        return AjaxResult.error("支付失败");
    }

    public boolean weixinPay(){
        return true;
    }

    //定时任务，每隔10分钟查询一次超过30分钟未支付的订单，将订单取消掉。
    @Scheduled(cron = "0 0/10 * * * ?")
    public void cancelNoPayOrder(){
        List<BsOrderInfo> bsOrderInfos = bsOrderInfoService.selectOver30NoPayOrder();
        bsOrderInfos.forEach(x -> x.setOrderUseStatus(OrderConstants.USE_STATUS_CANCEL));
        bsOrderInfoService.updateBatchById(bsOrderInfos);
    }

    //定时任务，每天凌晨1点查询未使用的订单，将状态改成已过期
    @Scheduled(cron = "0 0 1 * * ? ")
    public void overTimeOrder(){
        List<BsOrderInfo> bsOrderInfos = bsOrderInfoService.selectOverTimeOrder();
        bsOrderInfos.forEach(x -> x.setOrderUseStatus(OrderConstants.USE_STATUS_OVERTIME));
        bsOrderInfoService.updateBatchById(bsOrderInfos);
    }
}
